﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
using System.Linq.Expressions;
using System.Data.Common;
using System.Collections.Concurrent;
using System.Reflection;
using ED.Common.BaseModel;
using ED.Common.Extensions;

namespace ED.FreeSql.Core
{
    /// <summary>
    /// 仓储,开放主键类型
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TPrimaryKey"></typeparam>
    public class Repository<TEntity, TPrimaryKey> : IRepository<TEntity, TPrimaryKey> where TEntity : BaseEntity<TPrimaryKey>, new() where TPrimaryKey : struct
    {
        private readonly object deleteDto = new { IsDeleted = 1 };
        private DbTransaction Transaction { get => FreeExtensions.AsyncContext?.Tran; }

        public virtual IFreeSql Orm
        {
            get => FreeExtensions.FreeSql;
        }

        public virtual IUser User
        {
            get => FreeExtensions.User;
        }

        public Repository()
        {
            if (typeof(IAuditUpdated).IsAssignableFrom(typeof(TEntity)))
            {
                isAuditUpdate = true;
            }
            if (typeof(IAuditDeleted).IsAssignableFrom(typeof(TEntity)))
            {
                isAuditDelete = true;
            }
            if (typeof(IAuditCreated).IsAssignableFrom(typeof(TEntity)))
            {
                isAuditInsert = true;
            }
        }

        #region 删除
        public int Delete(TPrimaryKey? id)
        {
            if (id == null) return 0;
            if (!isAuditDelete) return HardDelete(id);
            return Orm.Update<TEntity>(id).WithTransaction(Transaction).SetDto(deleteDto).ExecuteAffrows();
        }

        public int Delete(IEnumerable<TPrimaryKey> ids)
        {
            if (!isAuditDelete) return HardDelete(ids);
            return Orm.Update<TEntity>(ids.ToArray()).WithTransaction(Transaction).SetDto(deleteDto).ExecuteAffrows();
        }

        public int Delete(Expression<Func<TEntity, bool>> predicate)
        {
            if (!isAuditDelete) return HardDelete(predicate);
            return Orm.Update<TEntity>().WithTransaction(Transaction).Where(predicate).SetDto(deleteDto).ExecuteAffrows();
        }

        public Task<int> DeleteAsync(TPrimaryKey? id, CancellationToken cancellationToken = default)
        {
            if (id == null) return Task.FromResult<int>(0);
            if (!isAuditDelete) return HardDeleteAsync(id, cancellationToken);
            return Orm.Update<TEntity>(id.Value).WithTransaction(Transaction).SetDto(deleteDto).ExecuteAffrowsAsync();
        }

        public Task<int> DeleteAsync(IEnumerable<TPrimaryKey> ids, CancellationToken cancellationToken = default)
        {
            if (!isAuditDelete) return HardDeleteAsync(ids, cancellationToken);
            return Orm.Update<TEntity>(ids.ToArray()).WithTransaction(Transaction).SetDto(deleteDto).ExecuteAffrowsAsync();
        }

        public Task<int> DeleteAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
        {
            if (!isAuditDelete) return HardDeleteAsync(predicate, cancellationToken);
            return Orm.Update<TEntity>().WithTransaction(Transaction).Where(predicate).SetDto(deleteDto).ExecuteAffrowsAsync();
        }
        #endregion

        #region 强制使用硬删除
        public int HardDelete(TPrimaryKey? id)
        {
            if (id == null) return 0;
            return Orm.Delete<TEntity>(id).WithTransaction(Transaction).ExecuteAffrows();
        }

        public int HardDelete(IEnumerable<TPrimaryKey> ids)
        {
            return Orm.Delete<TEntity>(ids).WithTransaction(Transaction).ExecuteAffrows();
        }

        public int HardDelete(Expression<Func<TEntity, bool>> predicate)
        {
            return Orm.Delete<TEntity>().WithTransaction(Transaction).Where(predicate).ExecuteAffrows();
        }

        public Task<int> HardDeleteAsync(TPrimaryKey? id, CancellationToken cancellationToken = default)
        {
            if (id == null) return Task.FromResult<int>(0);
            return Orm.Delete<TEntity>(id).WithTransaction(Transaction).ExecuteAffrowsAsync(cancellationToken);
        }

        public Task<int> HardDeleteAsync(IEnumerable<TPrimaryKey> ids, CancellationToken cancellationToken = default)
        {
            return Orm.Delete<TEntity>(ids.ToArray()).WithTransaction(Transaction).ExecuteAffrowsAsync(cancellationToken);
        }

        public Task<int> HardDeleteAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
        {
            return Orm.Delete<TEntity>().WithTransaction(Transaction).Where(predicate).ExecuteAffrowsAsync(cancellationToken);
        }
        #endregion

        private static ConcurrentDictionary<Type, Func<object, TEntity>> _mappers = new ConcurrentDictionary<Type, Func<object, TEntity>>();
        private static Func<object, TEntity> _getMapper(Type type)
        {
            return _mappers.GetOrAdd(type, dtoInst =>
            {
                var props = type.GetProperties();
                var props2 = typeof(TEntity).GetProperties();
                var newValue = new TEntity();
                foreach (var prop in props)
                {
                    var val = prop.GetValue(dtoInst);
                    props2.FirstOrDefault(p => p.Name == prop.Name)?.SetValue(newValue, val);
                }
                return newValue;
            });
        }

        #region 插入        
        public TEntity Insert(object dto)
        {
            var mapper = _getMapper(dto.GetType());
            var ent = mapper(dto);
            return Orm.Insert<TEntity>()
                .SetAuditValue(ent)
                .WithTransaction(Transaction)
                .ExecuteInserted().FirstOrDefault();
        }

        public ResponseDto Insert<ResponseDto>(object dto) where ResponseDto : class, new()
        {
            var mapper = _getMapper(dto.GetType());
            var ent = mapper(dto);
            ent = Orm.Insert<TEntity>()
                .SetAuditValue(ent)
                .WithTransaction(Transaction).ExecuteInserted().FirstOrDefault();
            return Orm.Select<TEntity>(ent.Id).WithTransaction(Transaction).ToOne<ResponseDto>();
        }

        public TEntity Insert(TEntity entity)
        {
            return Orm.Insert<TEntity>()
                .SetAuditValue(entity)
                .WithTransaction(Transaction)
                .ExecuteInserted().FirstOrDefault();
        }

        public List<TEntity> Insert(IEnumerable<TEntity> entitys)
        {
            return Orm.Insert<TEntity>()
                .SetAuditValue(entitys.ToList())
                .WithTransaction(Transaction)
                .ExecuteInserted();
        }

        public List<TEntity> Insert<Dto>(IEnumerable<Dto> dtos) where Dto : class, new()
        {
            var mapper = _getMapper(typeof(Dto));
            var list = new List<TEntity>();
            dtos.ForEach(dto => list.Add(mapper(dto)));
            return Orm.Insert<TEntity>()
                .SetAuditValue(list)
                .WithTransaction(Transaction)
                .ExecuteInserted();
        }

        public List<ResponseDto> Insert<Dto, ResponseDto>(IEnumerable<Dto> dtos) where Dto : class, new() where ResponseDto : class, new()
        {
            var mapper = _getMapper(typeof(Dto));
            var list = new List<TEntity>();
            dtos.ForEach(dto => list.Add(mapper(dto)));
            var ents = Orm.Insert<TEntity>()
                .SetAuditValue(list)
                .WithTransaction(Transaction)
                .ExecuteInserted();
            var ids = ents.Select(ent => ent.Id).ToArray();
            return Orm.Select<TEntity>().Where(i => ids.Contains(i.Id)).WithTransaction(Transaction).ToList<ResponseDto>();
        }

        public Task<TEntity> InsertAsync(TEntity entity, CancellationToken cancellationToken = default)
        {
            
            return Orm.Insert<TEntity>()
                .SetAuditValue(entity)
                .WithTransaction(Transaction)
                .ExecuteInsertedAsync(cancellationToken).ContinueWith<TEntity>(pre => pre.Result.FirstOrDefault());
        }

        public Task<TEntity> InsertAsync(object dto, CancellationToken cancellationToken = default)
        {
            var mapper = _getMapper(dto.GetType());
            var ent = mapper(dto);
            return Orm.Insert<TEntity>()
                .SetAuditValue(ent)
                .WithTransaction(Transaction)
                .ExecuteInsertedAsync(cancellationToken)
                .ContinueWith<TEntity>(pre => pre.Result.FirstOrDefault());
        }

        public async Task<ResponseDto> InsertAsync<ResponseDto>(object dto, CancellationToken cancellationToken = default) where ResponseDto : class, new()
        {
            var mapper = _getMapper(dto.GetType());
            var ent = mapper(dto);
            var ents = await Orm.Insert<TEntity>()
                 .SetAuditValue(ent)
                 .WithTransaction(Transaction)
                 .ExecuteInsertedAsync(cancellationToken);
            return Orm.Select<TEntity>(ents.FirstOrDefault().Id).WithTransaction(Transaction).ToOne<ResponseDto>();
        }

        public Task<List<TEntity>> InsertAsync(IEnumerable<TEntity> entitys, CancellationToken cancellationToken = default)
        {
            return Orm.Insert<TEntity>()
                .SetAuditValue(entitys.ToList())
                .WithTransaction(Transaction)
                .ExecuteInsertedAsync(cancellationToken);
        }

        public Task<List<TEntity>> InsertAsync<Dto>(IEnumerable<Dto> dtos, CancellationToken cancellationToken = default)
        {
            var mapper = _getMapper(typeof(Dto));
            var list = new List<TEntity>();
            dtos.ForEach(dto => list.Add(mapper(dto)));
            return Orm.Insert<TEntity>()
                .SetAuditValue(list)
                .WithTransaction(Transaction)
                .ExecuteInsertedAsync(cancellationToken);
        }

        public async Task<List<ResponseDto>> InsertAsync<Dto, ResponseDto>(IEnumerable<Dto> dtos, CancellationToken cancellationToken = default) where Dto : class, new() where ResponseDto : class, new()
        {
            var mapper = _getMapper(typeof(Dto));
            var list = new List<TEntity>();
            dtos.ForEach(dto => list.Add(mapper(dto)));
            var ents = await Orm.Insert<TEntity>()
                .SetAuditValue(list)
                .WithTransaction(Transaction)
                .ExecuteInsertedAsync(cancellationToken);
            var ids = ents.Select(e => e.Id).ToArray();
            return await Orm.Select<TEntity>().Where(i => ids.Contains(i.Id)).WithTransaction(Transaction).ToListAsync<ResponseDto>();
        }
        #endregion

        #region 更新
        public TEntity Update(TEntity entity)
        {
            return Orm.Update<TEntity>()
                .WithTransaction(Transaction)
                .SetAuditValue(entity, false)
                .ExecuteUpdated().FirstOrDefault();
        }

        public TEntity Update(object dto)
        {
            var id = dto.GetType().GetProperty(nameof(BaseEntity.Id)).GetValue(dto);
            return Orm.Update<TEntity>(id)
                .WithTransaction(Transaction)
                .SetAuditValue(dto, true)
                .ExecuteUpdated().FirstOrDefault();
        }

        public ResponseDto Update<ResponseDto>(object dto) where ResponseDto : class, new()
        {
            var id = dto.GetType().GetProperty(nameof(BaseEntity.Id)).GetValue(dto);
            Orm.Update<TEntity>(id)
                 .WithTransaction(Transaction)
                 .SetAuditValue(dto, true)
                 .ExecuteAffrows();
            return Orm.Select<TEntity>(id).WithTransaction(Transaction).ToOne<ResponseDto>();
        }

        public List<TEntity> Update(IEnumerable<TEntity> entitys)
        {
            return Orm.Update<TEntity>()
                .WithTransaction(Transaction)
                .SetAuditValue(entitys.ToList())
                .ExecuteUpdated();
        }

        public List<TEntity> Update(Expression<Func<TEntity, bool>> predicate, object dto)
        {
            return Orm.Update<TEntity>()
                .WithTransaction(Transaction)
                .SetAuditValue(dto, true)
                .Where(predicate).ExecuteUpdated();
        }

        public List<ResponseDto> Update<ResponseDto>(Expression<Func<TEntity, bool>> predicate, object dto) where ResponseDto : class, new()
        {
            var entitys = Orm.Update<TEntity>()
                .WithTransaction(Transaction)
                .SetAuditValue(dto, true)
                .Where(predicate)
                .ExecuteUpdated();
            var ids = entitys.Select(e => e.Id).ToList();
            return Orm.Select<TEntity>().Where(i => ids.Contains(i.Id)).WithTransaction(Transaction).ToList<ResponseDto>();
        }

        //异步

        public Task<List<TEntity>> UpdateAsync(Expression<Func<TEntity, bool>> predicate, object dto, CancellationToken cancellationToken = default)
        {
            return Orm.Update<TEntity>()
                .WithTransaction(Transaction)
                .SetAuditValue(dto, true)
                .Where(predicate)
                .ExecuteUpdatedAsync(cancellationToken);
        }

        public Task<TEntity> UpdateAsync(object dto, CancellationToken cancellationToken = default)
        {
            var id = dto.GetType().GetProperty(nameof(BaseEntity.Id)).GetValue(dto);
            return Orm.Update<TEntity>(id)
                .WithTransaction(Transaction)
                .SetAuditValue(dto, true)
                .ExecuteUpdatedAsync(cancellationToken).ContinueWith(pre => pre.Result.FirstOrDefault());
        }

        public async Task<ResponseDto> UpdateAsync<ResponseDto>(object dto, CancellationToken cancellationToken = default) where ResponseDto : class, new()
        {
            var id = dto.GetType().GetProperty(nameof(BaseEntity.Id)).GetValue(dto);
            var ents = await Orm.Update<TEntity>(id)
                 .WithTransaction(Transaction)
                 .SetAuditValue(dto, true)
                 .ExecuteUpdatedAsync(cancellationToken);
            var ids = ents.Select(e => e.Id).ToArray();
            return await Orm.Select<TEntity>(id).WithTransaction(Transaction).ToOneAsync<ResponseDto>();
        }

        public Task<TEntity> UpdateAsync(TEntity entity, CancellationToken cancellationToken = default)
        {
            return Orm.Update<TEntity>()
                .WithTransaction(Transaction)
                .SetAuditValue(entity, false)
                .ExecuteUpdatedAsync(cancellationToken)
                .ContinueWith(pre => pre.Result.FirstOrDefault());
        }

        public Task<List<TEntity>> UpdateAsync(IEnumerable<TEntity> entitys, CancellationToken cancellationToken = default)
        {
            return Orm.Update<TEntity>()
                .WithTransaction(Transaction)
                .SetAuditValue(entitys.ToList())
                .ExecuteUpdatedAsync(cancellationToken);
        }

        public async Task<List<ResponseDto>> UpdateAsync<ResponseDto>(Expression<Func<TEntity, bool>> predicate, object dto, CancellationToken cancellationToken = default) where ResponseDto : class, new()
        {
            var ents = await Orm.Update<TEntity>()
                .WithTransaction(Transaction)
                .SetAuditValue(dto, true)
                .Where(predicate)
                .ExecuteUpdatedAsync(cancellationToken);
            var ids = ents.Select(e => e.Id).ToArray();
            return await Orm.Select<TEntity>().Where(i => ids.Contains(i.Id)).WithTransaction(Transaction).ToListAsync<ResponseDto>();
        }
        #endregion

        #region 查询
        public TEntity Get(TPrimaryKey? id)
        {
            if (id == null) return null;
            return Orm.Select<TEntity>(id).WithTransaction(Transaction).ToOne();
        }

        public Dto Get<Dto>(TPrimaryKey? id) where Dto : class, new()
        {
            if (id == null) return default(Dto);
            return Orm.Select<TEntity>(id).WithTransaction(Transaction).ToOne<Dto>();
        }

        public Dto GetLazy<Dto>(TPrimaryKey? id) where Dto : class, new()
        {
            if (id == null) return default(Dto);
            return Orm.Select<TEntity>(id).WithTransaction(Transaction).ToOne().Mapper<Dto>();
        }

        public TEntity Get(Expression<Func<TEntity, bool>> predicate)
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).ToOne();
        }

        public Dto Get<Dto>(Expression<Func<TEntity, bool>> predicate) where Dto : class, new()
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).ToOne<Dto>();
        }

        public Dto GetLazy<Dto>(Expression<Func<TEntity, bool>> predicate) where Dto : class, new()
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).ToOne().Mapper<Dto>();
        }

        public List<TEntity> GetList(IEnumerable<TPrimaryKey> ids)
        {
            return Orm.Select<TEntity>(ids.ToArray()).WithTransaction(Transaction).ToList();
        }

        public List<Dto> GetList<Dto>(IEnumerable<TPrimaryKey> ids) where Dto : class, new()
        {
            return Orm.Select<TEntity>(ids.ToArray()).WithTransaction(Transaction).ToList<Dto>();
        }

        public List<Dto> GetListLazy<Dto>(IEnumerable<TPrimaryKey> ids) where Dto : class, new()
        {
            return Orm.Select<TEntity>(ids.ToArray()).WithTransaction(Transaction).ToList().Mapper<List<Dto>>();
        }

        public long GetCount(Expression<Func<TEntity, bool>> predicate = null)
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).Count();
        }
        public List<TEntity> GetList(Expression<Func<TEntity, bool>> predicate = null)
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).ToList();
        }

        public List<Dto> GetList<Dto>(Expression<Func<TEntity, bool>> predicate = null) where Dto : class, new()
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).ToList<Dto>();
        }

        public List<Dto> GetListLazy<Dto>(Expression<Func<TEntity, bool>> predicate = null) where Dto : class, new()
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).ToList().Mapper<List<Dto>>();
        }

        public PageOut<TEntity> GetPage(int pageIndex, int pageSize, Expression<Func<TEntity, bool>> predicate = null)
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).GetPage(pageIndex, pageSize);
        }

        public PageOut<Dto> GetPage<Dto>(int pageIndex, int pageSize, Expression<Func<TEntity, bool>> predicate = null) where Dto : class, new()
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).GetPage<TEntity, Dto>(pageIndex, pageSize);
        }
        public PageOut<TEntity> GetPage(BaseReqPage page, Expression<Func<TEntity, bool>> predicate = null)
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).GetPage(page.PageIndex, page.PageSize);
        }

        public PageOut<Dto> GetPage<Dto>(BaseReqPage page, Expression<Func<TEntity, bool>> predicate = null) where Dto : class, new()
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).GetPage<TEntity, Dto>(page.PageIndex, page.PageSize);
        }
        //异步

        public Task<TEntity> GetAsync(TPrimaryKey? id, CancellationToken cancellationToken = default)
        {
            if (id == null) return Task.FromResult<TEntity>(null);
            return Orm.Select<TEntity>(id).WithTransaction(Transaction).ToOneAsync(cancellationToken);
        }

        public Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).ToOneAsync(cancellationToken);
        }

        public Task<Dto> GetAsync<Dto>(TPrimaryKey? id, CancellationToken cancellationToken = default) where Dto : class, new()
        {
            if (id == null) return Task.FromResult<Dto>(default(Dto));
            return Orm.Select<TEntity>(id).WithTransaction(Transaction).ToOneAsync<Dto>(cancellationToken);
        }

        public Task<Dto> GetLazyAsync<Dto>(TPrimaryKey? id, CancellationToken cancellationToken = default) where Dto : class, new()
        {
            if (id == null) return Task.FromResult<Dto>(default(Dto));
            return Orm.Select<TEntity>(id).WithTransaction(Transaction).ToOneAsync(cancellationToken).ContinueWith(i => i.Result.Mapper<Dto>());
        }

        public Task<Dto> GetAsync<Dto>(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default) where Dto : class, new()
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).ToOneAsync<Dto>(cancellationToken);
        }

        public Task<Dto> GetLazyAsync<Dto>(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default) where Dto : class, new()
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).ToOneAsync(cancellationToken).ContinueWith(i => i.Result.Mapper<Dto>());
        }

        public Task<List<TEntity>> GetListAsync(IEnumerable<TPrimaryKey> ids, CancellationToken cancellationToken = default)
        {
            return Orm.Select<TEntity>(ids.ToArray()).WithTransaction(Transaction).ToListAsync(false, cancellationToken);
        }

        public Task<List<Dto>> GetListAsync<Dto>(IEnumerable<TPrimaryKey> ids, CancellationToken cancellationToken = default) where Dto : class, new()
        {
            return Orm.Select<TEntity>(ids.ToArray()).WithTransaction(Transaction).ToListAsync<Dto>(cancellationToken);
        }

        public Task<List<Dto>> GetListLazyAsync<Dto>(IEnumerable<TPrimaryKey> ids, CancellationToken cancellationToken = default) where Dto : class, new()
        {
            return Orm.Select<TEntity>(ids.ToArray()).WithTransaction(Transaction).ToListAsync(cancellationToken: cancellationToken).ContinueWith(i => i.Result.Mapper<List<Dto>>());
        }

        public Task<long> GetCountAsync(CancellationToken cancellationToken = default)
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).CountAsync(cancellationToken);
        }

        public Task<long> GetCountAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).CountAsync(cancellationToken);
        }

        public Task<List<TEntity>> GetListAsync(CancellationToken cancellationToken = default)
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).ToListAsync(false, cancellationToken);
        }

        public Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).ToListAsync(false, cancellationToken);
        }

        public Task<List<Dto>> GetListAsync<Dto>(CancellationToken cancellationToken = default) where Dto : class, new()
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).ToListAsync<Dto>(cancellationToken);
        }

        public Task<List<Dto>> GetListLazyAsync<Dto>(CancellationToken cancellationToken = default) where Dto : class, new()
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).ToListAsync(cancellationToken: cancellationToken)
                .ContinueWith(i => i.Result.Mapper<List<Dto>>());
        }

        public Task<List<Dto>> GetListAsync<Dto>(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default) where Dto : class, new()
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).ToListAsync<Dto>(cancellationToken);
        }

        public Task<List<Dto>> GetListLazyAsync<Dto>(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default) where Dto : class, new()
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).ToListAsync(cancellationToken: cancellationToken).ContinueWith(i => i.Result.Mapper<List<Dto>>());
        }

        public Task<PageOut<TEntity>> GetPageAsync(int pageIndex, int pageSize, CancellationToken cancellationToken = default)
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).GetPageAsync(pageIndex, pageSize, cancellationToken);
        }

        public Task<PageOut<TEntity>> GetPageAsync(BaseReqPage page, CancellationToken cancellationToken = default)
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).GetPageAsync(page.PageIndex, page.PageSize, cancellationToken);
        }

        public Task<PageOut<TEntity>> GetPageAsync(int pageIndex, int pageSize, Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).GetPageAsync(pageIndex, pageSize, cancellationToken);
        }

        public Task<PageOut<TEntity>> GetPageAsync(BaseReqPage page, Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).GetPageAsync(page.PageIndex, page.PageSize, cancellationToken);
        }

        public Task<PageOut<Dto>> GetPageAsync<Dto>(int pageIndex, int pageSize, CancellationToken cancellationToken = default) where Dto : class, new()
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).GetPageAsync<TEntity, Dto>(pageIndex, pageSize, cancellationToken);
        }

        public Task<PageOut<Dto>> GetPageAsync<Dto>(BaseReqPage page, CancellationToken cancellationToken = default) where Dto : class, new()
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).GetPageAsync<TEntity, Dto>(page.PageIndex, page.PageSize, cancellationToken);
        }

        public Task<PageOut<Dto>> GetPageAsync<Dto>(int pageIndex, int pageSize, Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default) where Dto : class, new()
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).GetPageAsync<TEntity, Dto>(pageIndex, pageSize, cancellationToken);
        }

        public Task<PageOut<Dto>> GetPageAsync<Dto>(BaseReqPage page, Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default) where Dto : class, new()
        {
            return Orm.Select<TEntity>().WithTransaction(Transaction).Where(predicate).GetPageAsync<TEntity, Dto>(page.PageIndex, page.PageSize, cancellationToken);
        }

        #endregion

        #region 强制使用硬查询(不需要此功能)
        //public TEntity HardGet(TPrimaryKey? id)
        //{
        //    if (id == null) return null;
        //    return Orm.Select<TEntity>(id).UserHardQuery().ToOne();
        //}

        //public Dto HardGet<Dto>(TPrimaryKey? id) where Dto : class, new()
        //{
        //    if (id == null) return default(Dto);
        //    return Orm.Select<TEntity>(id).UserHardQuery().ToOne<Dto>();
        //}

        //public TEntity HardGet(Expression<Func<TEntity, bool>> predicate)
        //{
        //    return Orm.Select<TEntity>().UserHardQuery().Where(predicate).ToOne();
        //}

        //public Dto HardGet<Dto>(Expression<Func<TEntity, bool>> predicate) where Dto : class, new()
        //{
        //    return Orm.Select<TEntity>().UserHardQuery().Where(predicate).ToOne<Dto>();
        //}

        //public List<TEntity> HardGetList(IEnumerable<TPrimaryKey> ids)
        //{
        //    return Orm.Select<TEntity>(ids.ToArray()).UserHardQuery().ToList();
        //}

        //public List<Dto> HardGetList<Dto>(IEnumerable<TPrimaryKey> ids) where Dto : class, new()
        //{
        //    return Orm.Select<TEntity>(ids.ToArray()).UserHardQuery().ToList<Dto>();
        //}

        //public long HardGetCount(Expression<Func<TEntity, bool>> predicate = null)
        //{
        //    return Orm.Select<TEntity>().Where(predicate).UserHardQuery().Count();
        //}
        //public List<TEntity> HardGetList(Expression<Func<TEntity, bool>> predicate = null)
        //{
        //    return Orm.Select<TEntity>().Where(predicate).UserHardQuery().ToList();
        //}

        //public List<Dto> HardGetList<Dto>(Expression<Func<TEntity, bool>> predicate = null) where Dto : class, new()
        //{
        //    return Orm.Select<TEntity>().Where(predicate).UserHardQuery().ToList<Dto>();
        //}

        //public PageOut<TEntity> HardGetPage(int pageIndex, int pageSize, Expression<Func<TEntity, bool>> predicate = null)
        //{
        //    return Orm.Select<TEntity>().Where(predicate).UserHardQuery().GetPage(pageIndex, pageSize);
        //}

        //public PageOut<Dto> HardGetPage<Dto>(int pageIndex, int pageSize, Expression<Func<TEntity, bool>> predicate = null) where Dto : class, new()
        //{
        //    return Orm.Select<TEntity>().Where(predicate).UserHardQuery().GetPage<TEntity, Dto>(pageIndex, pageSize);
        //}

        ////异步

        //public Task<TEntity> HardGetAsync(TPrimaryKey? id, CancellationToken cancellationToken = default)
        //{
        //    if (id == null) return Task.FromResult<TEntity>(null);
        //    return Orm.Select<TEntity>(id).UserHardQuery().ToOneAsync(cancellationToken);
        //}

        //public Task<TEntity> HardGetAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
        //{
        //    return Orm.Select<TEntity>().Where(predicate).UserHardQuery().ToOneAsync(cancellationToken);
        //}

        //public Task<Dto> HardGetAsync<Dto>(TPrimaryKey? id, CancellationToken cancellationToken = default) where Dto : class, new()
        //{
        //    if (id == null) return Task.FromResult<Dto>(default(Dto));
        //    return Orm.Select<TEntity>(id).UserHardQuery().ToOneAsync<Dto>(cancellationToken);
        //}

        //public Task<Dto> HardGetAsync<Dto>(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default) where Dto : class, new()
        //{
        //    return Orm.Select<TEntity>().Where(predicate).UserHardQuery().ToOneAsync<Dto>(cancellationToken);
        //}

        //public Task<List<TEntity>> HardGetListAsync(IEnumerable<TPrimaryKey> ids, CancellationToken cancellationToken = default)
        //{
        //    return Orm.Select<TEntity>(ids.ToArray()).UserHardQuery().ToListAsync(false, cancellationToken);
        //}

        //public Task<List<Dto>> HardGetListAsync<Dto>(IEnumerable<TPrimaryKey> ids, CancellationToken cancellationToken = default) where Dto : class, new()
        //{
        //    return Orm.Select<TEntity>(ids.ToArray()).UserHardQuery().ToListAsync<Dto>(cancellationToken);
        //}

        //public Task<long> HardGetCountAsync(CancellationToken cancellationToken = default)
        //{
        //    return Orm.Select<TEntity>().UserHardQuery().CountAsync(cancellationToken);
        //}

        //public Task<long> HardGetCountAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
        //{
        //    return Orm.Select<TEntity>().Where(predicate).UserHardQuery().CountAsync(cancellationToken);
        //}

        //public Task<List<TEntity>> HardGetListAsync(CancellationToken cancellationToken = default)
        //{
        //    return Orm.Select<TEntity>().UserHardQuery().ToListAsync(false, cancellationToken);
        //}

        //public Task<List<TEntity>> HardGetListAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
        //{
        //    return Orm.Select<TEntity>().Where(predicate).UserHardQuery().ToListAsync(false, cancellationToken);
        //}

        //public Task<List<Dto>> HardGetListAsync<Dto>(CancellationToken cancellationToken = default) where Dto : class, new()
        //{
        //    return Orm.Select<TEntity>().UserHardQuery().ToListAsync<Dto>(cancellationToken);
        //}

        //public Task<List<Dto>> HardGetListAsync<Dto>(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default) where Dto : class, new()
        //{
        //    return Orm.Select<TEntity>().Where(predicate).UserHardQuery().ToListAsync<Dto>(cancellationToken);
        //}

        //public Task<PageOut<TEntity>> HardGetPageAsync(int pageIndex, int pageSize, CancellationToken cancellationToken = default)
        //{
        //    return Orm.Select<TEntity>().UserHardQuery().GetPageAsync(pageIndex, pageSize, cancellationToken);
        //}

        //public Task<PageOut<TEntity>> HardGetPageAsync(int pageIndex, int pageSize, Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
        //{
        //    return Orm.Select<TEntity>().UserHardQuery().Where(predicate).GetPageAsync(pageIndex, pageSize, cancellationToken);
        //}

        //public Task<PageOut<Dto>> HardGetPageAsync<Dto>(int pageIndex, int pageSize, CancellationToken cancellationToken = default) where Dto : class, new()
        //{
        //    return Orm.Select<TEntity>().UserHardQuery().GetPageAsync<TEntity, Dto>(pageIndex, pageSize, cancellationToken);
        //}

        //public Task<PageOut<Dto>> HardGetPageAsync<Dto>(int pageIndex, int pageSize, Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default) where Dto : class, new()
        //{
        //    return Orm.Select<TEntity>().Where(predicate).UserHardQuery().GetPageAsync<TEntity, Dto>(pageIndex, pageSize, cancellationToken);
        //}
        #endregion

        #region 审计属性判断
        private bool isAuditUpdate = false;
        /// <summary>
        /// 是否是更新审计实体
        /// </summary>
        public bool IsAuditUpdate
        {
            get
            {
                return isAuditUpdate;
            }
        }

        private bool isAuditDelete = false;
        /// <summary>
        /// 是否是删除审计实体
        /// </summary>
        public bool IsAuditDelete
        {
            get
            {
                return isAuditDelete;
            }
        }

        private bool isAuditInsert = false;
        /// <summary>
        /// 是否是插入审计实体
        /// </summary>
        public bool IsAuditInsert
        {
            get
            {
                return isAuditInsert;
            }
        }
        #endregion

    }

    /// <summary>
    /// 仓储,使用int作为主键类型
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public class Repository<TEntity> : Repository<TEntity, int>, IRepository<TEntity> where TEntity : BaseEntity<int>, new()
    {
    }
}
